<template>
  <div class="min-h-screen py-8 px-4 sm:px-6 lg:px-8">
    <div class="max-w-4xl mx-auto">
      <!-- 页面标题 -->
      <div class="text-center mb-12">
        <h1 class="text-4xl font-bold mb-4 tech-text">Barcode Detection API</h1>
        <p class="text-gray-300 text-lg">
          检测和识别图像中的条形码和二维码，支持多种格式的码识别
        </p>
      </div>

      <!-- 浏览器支持提示 -->
      <div v-if="!isSupported" class="tech-card mb-8 border-yellow-600">
        <div class="flex items-center mb-4">
          <i class="i-carbon-warning text-yellow-500 text-xl mr-3"></i>
          <h3 class="text-xl font-semibold text-yellow-500">浏览器支持提示</h3>
        </div>
        <p class="text-gray-300 mb-4">
          您的浏览器不支持 Barcode Detection API。此功能需要 Chrome 83+ 或其他支持的浏览器。
        </p>
        <p class="text-gray-400 text-sm">
          注意：此 API 目前仍在实验阶段，可能需要启用实验性功能。
        </p>
      </div>

      <!-- 检测方式选择 -->
      <div class="tech-card mb-8">
        <h2 class="text-2xl font-semibold mb-6 text-white">检测方式</h2>
        
        <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
          <!-- 摄像头检测 -->
          <div class="bg-gray-800 rounded-lg p-6">
            <h3 class="text-lg font-semibold text-white mb-4 flex items-center">
              <i class="i-carbon-camera text-blue-400 mr-3"></i>
              摄像头检测
            </h3>
            <p class="text-gray-300 text-sm mb-4">使用设备摄像头实时检测条形码</p>
            <button
              @click="startCameraDetection"
              :disabled="!isSupported || isCameraActive"
              class="tech-button w-full disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <i class="i-carbon-video mr-2"></i>
              {{ isCameraActive ? '摄像头已启动' : '启动摄像头' }}
            </button>
          </div>

          <!-- 文件上传检测 -->
          <div class="bg-gray-800 rounded-lg p-6">
            <h3 class="text-lg font-semibold text-white mb-4 flex items-center">
              <i class="i-carbon-document-add text-green-400 mr-3"></i>
              文件检测
            </h3>
            <p class="text-gray-300 text-sm mb-4">上传图片文件进行条形码检测</p>
            <input
              ref="fileInput"
              type="file"
              accept="image/*"
              @change="handleFileUpload"
              class="hidden"
            >
            <button
              @click="fileInput?.click()"
              :disabled="!isSupported"
              class="bg-green-600 hover:bg-green-700 disabled:bg-gray-600 disabled:cursor-not-allowed text-white px-4 py-3 rounded-lg transition-colors w-full"
            >
              <i class="i-carbon-cloud-upload mr-2"></i>
              选择图片
            </button>
          </div>

          <!-- URL 检测 -->
          <div class="bg-gray-800 rounded-lg p-6">
            <h3 class="text-lg font-semibold text-white mb-4 flex items-center">
              <i class="i-carbon-link text-orange-400 mr-3"></i>
              URL 检测
            </h3>
            <p class="text-gray-300 text-sm mb-4">通过图片URL进行条形码检测</p>
            <button
              @click="showUrlInput = !showUrlInput"
              :disabled="!isSupported"
              class="bg-orange-600 hover:bg-orange-700 disabled:bg-gray-600 disabled:cursor-not-allowed text-white px-4 py-3 rounded-lg transition-colors w-full"
            >
              <i class="i-carbon-earth mr-2"></i>
              输入URL
            </button>
          </div>
        </div>

        <!-- URL 输入框 -->
        <div v-if="showUrlInput" class="mt-6 bg-gray-800 rounded-lg p-6">
          <label class="block text-gray-300 mb-3">图片URL:</label>
          <div class="flex gap-3">
            <input
              v-model="imageUrl"
              type="url"
              placeholder="https://example.com/barcode.jpg"
              class="flex-1 bg-gray-700 text-white border border-gray-600 rounded-lg px-3 py-2"
            >
            <button
              @click="detectFromUrl"
              :disabled="!imageUrl.trim()"
              class="tech-button disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <i class="i-carbon-search mr-2"></i>
              检测
            </button>
          </div>
        </div>
      </div>

      <!-- 摄像头预览 -->
      <div v-if="isCameraActive" class="tech-card mb-8">
        <h3 class="text-xl font-semibold mb-6 text-white">摄像头预览</h3>
        
        <div class="relative bg-gray-900 rounded-lg overflow-hidden">
          <video
            ref="videoElement"
            autoplay
            muted
            playsinline
            class="w-full max-h-96 object-cover"
          ></video>
          
          <!-- 检测框覆盖层 -->
          <canvas
            ref="overlayCanvas"
            class="absolute top-0 left-0 w-full h-full pointer-events-none"
          ></canvas>
        </div>

        <div class="flex gap-4 mt-4">
          <button
            @click="captureFrame"
            class="tech-button"
          >
            <i class="i-carbon-camera mr-2"></i>
            拍照检测
          </button>
          
          <button
            @click="stopCamera"
            class="bg-red-600 hover:bg-red-700 text-white px-6 py-3 rounded-lg transition-colors"
          >
            <i class="i-carbon-stop mr-2"></i>
            停止摄像头
          </button>
          
          <label class="flex items-center text-gray-300">
            <input
              v-model="continuousDetection"
              type="checkbox"
              class="mr-2"
            >
            连续检测
          </label>
        </div>
      </div>

      <!-- 图片预览和检测结果 -->
      <div v-if="currentImage" class="tech-card mb-8">
        <h3 class="text-xl font-semibold mb-6 text-white">检测结果</h3>
        
        <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
          <!-- 图片预览 -->
          <div>
            <h4 class="text-lg font-semibold text-white mb-3">原始图片</h4>
            <div class="relative bg-gray-900 rounded-lg overflow-hidden">
              <img
                ref="imageElement"
                :src="currentImage"
                alt="检测图片"
                crossorigin="anonymous"
                class="w-full max-h-80 object-contain"
                @load="onImageLoad"
                @error="onImageError"
              >
              <!-- 检测框覆盖层 -->
              <canvas
                ref="imageOverlayCanvas"
                class="absolute top-0 left-0 w-full h-full pointer-events-none"
              ></canvas>
            </div>
          </div>

          <!-- 检测结果 -->
          <div>
            <h4 class="text-lg font-semibold text-white mb-3">
              检测到的条形码 ({{ detectedBarcodes.length }})
            </h4>
            
            <div v-if="detectedBarcodes.length > 0" class="space-y-4">
              <div
                v-for="(barcode, index) in detectedBarcodes"
                :key="index"
                class="bg-gray-800 rounded-lg p-4"
              >
                <div class="flex justify-between items-start mb-3">
                  <div>
                    <h5 class="text-white font-semibold">条形码 {{ index + 1 }}</h5>
                    <p class="text-gray-400 text-sm">格式: {{ barcode.format }}</p>
                  </div>
                  <button
                    @click="copyToClipboard(barcode.rawValue)"
                    class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm transition-colors"
                  >
                    <i class="i-carbon-copy mr-1"></i>
                    复制
                  </button>
                </div>
                
                <div class="bg-gray-900 rounded p-3 mb-3">
                  <p class="text-green-400 font-mono text-sm break-all">{{ barcode.rawValue }}</p>
                </div>
                
                <div class="grid grid-cols-2 gap-4 text-xs text-gray-400">
                  <div>
                    <span>位置: </span>
                    <span class="text-white">
                      ({{ Math.round(barcode.boundingBox.x) }}, {{ Math.round(barcode.boundingBox.y) }})
                    </span>
                  </div>
                  <div>
                    <span>大小: </span>
                    <span class="text-white">
                      {{ Math.round(barcode.boundingBox.width) }} × {{ Math.round(barcode.boundingBox.height) }}
                    </span>
                  </div>
                </div>
              </div>
            </div>

            <div v-else-if="hasDetected" class="text-center text-gray-400 py-8">
              <i class="i-carbon-search text-4xl mb-4 block mx-auto opacity-50"></i>
              <p>未检测到条形码</p>
              <p class="text-sm mt-2">请尝试使用包含清晰条形码的图片</p>
            </div>

            <div v-if="isDetecting" class="text-center text-gray-400 py-8">
              <i class="i-carbon-loading text-4xl mb-4 block mx-auto animate-spin"></i>
              <p>正在检测条形码...</p>
            </div>
          </div>
        </div>
      </div>

      <!-- 支持的格式 -->
      <div class="tech-card mb-8">
        <h3 class="text-xl font-semibold mb-6 text-white">支持的条形码格式</h3>
        
        <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
          <div
            v-for="format in supportedFormats"
            :key="format.name"
            class="bg-gray-800 rounded-lg p-4 text-center"
          >
            <div class="text-2xl mb-2">{{ format.icon }}</div>
            <h4 class="text-white font-semibold text-sm">{{ format.name }}</h4>
            <p class="text-gray-400 text-xs mt-1">{{ format.description }}</p>
          </div>
        </div>
      </div>

      <!-- 检测历史 -->
      <div v-if="detectionHistory.length > 0" class="tech-card mb-8">
        <h3 class="text-xl font-semibold mb-4 text-white">检测历史</h3>
        
        <div class="space-y-3 max-h-64 overflow-y-auto">
          <div
            v-for="(record, index) in detectionHistory.slice().reverse()"
            :key="index"
            class="bg-gray-800 rounded-lg p-4"
          >
            <div class="flex justify-between items-start">
              <div class="flex-1">
                <div class="flex items-center gap-2 mb-2">
                  <span class="text-white font-semibold">{{ record.format }}</span>
                  <span class="text-gray-400 text-sm">{{ formatTime(record.timestamp) }}</span>
                </div>
                <p class="text-gray-300 font-mono text-sm break-all">{{ record.value }}</p>
              </div>
              <button
                @click="copyToClipboard(record.value)"
                class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm transition-colors ml-3"
              >
                <i class="i-carbon-copy mr-1"></i>
                复制
              </button>
            </div>
          </div>
        </div>
        
        <div class="mt-4 pt-4 border-t border-gray-700">
          <button
            @click="clearHistory"
            class="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg transition-colors text-sm"
          >
            <i class="i-carbon-trash-can mr-1"></i>
            清空历史
          </button>
        </div>
      </div>

      <!-- 错误信息 -->
      <div v-if="error" class="tech-card border-red-600 mb-8">
        <div class="flex items-center mb-2">
          <i class="i-carbon-warning text-red-500 text-xl mr-3"></i>
          <h3 class="text-xl font-semibold text-red-500">错误</h3>
        </div>
        <p class="text-gray-300">{{ error }}</p>
      </div>

      <!-- API 信息 -->
      <div class="tech-card">
        <h3 class="text-xl font-semibold mb-4 text-white">API 信息</h3>
        <div class="space-y-4 text-gray-300">
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">浏览器支持</h4>
            <p>Chrome 83+ (实验性功能，需要启用)</p>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">主要方法</h4>
            <ul class="list-disc list-inside space-y-1">
              <li><code class="bg-gray-800 px-2 py-1 rounded">new BarcodeDetector(options)</code> - 创建检测器</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">detector.detect(imageSource)</code> - 检测条形码</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">BarcodeDetector.getSupportedFormats()</code> - 获取支持格式</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">使用场景</h4>
            <ul class="list-disc list-inside space-y-1">
              <li>商品扫码和库存管理</li>
              <li>票务和门禁系统</li>
              <li>物流和快递追踪</li>
              <li>移动支付和电子凭证</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">启用方法</h4>
            <ul class="list-disc list-inside space-y-1">
              <li>Chrome: 访问 chrome://flags/#enable-experimental-web-platform-features</li>
              <li>启用 "Experimental Web Platform features" 标志</li>
              <li>重启浏览器后生效</li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, useTemplateRef, watch } from 'vue'

// 类型定义
interface DetectedBarcode {
  boundingBox: DOMRectReadOnly
  cornerPoints: Array<{ x: number; y: number }>
  format: string
  rawValue: string
}

interface DetectionRecord {
  value: string
  format: string
  timestamp: number
}

// 响应式状态
const isSupported = ref(false)
const isCameraActive = ref(false)
const continuousDetection = ref(false)
const showUrlInput = ref(false)
const imageUrl = ref('')
const currentImage = ref('')
const detectedBarcodes = ref<DetectedBarcode[]>([])
const detectionHistory = ref<DetectionRecord[]>([])
const isDetecting = ref(false)
const hasDetected = ref(false)
const error = ref('')

// 模板引用
const videoElement = useTemplateRef<HTMLVideoElement>('videoElement')
const imageElement = useTemplateRef<HTMLImageElement>('imageElement')
const overlayCanvas = useTemplateRef<HTMLCanvasElement>('overlayCanvas')
const imageOverlayCanvas = useTemplateRef<HTMLCanvasElement>('imageOverlayCanvas')
const fileInput = useTemplateRef<HTMLInputElement>('fileInput')

// 媒体流和检测器
let mediaStream: MediaStream | null = null
let barcodeDetector: any = null
let detectionInterval: ReturnType<typeof setInterval> | null = null

// 支持的格式
const supportedFormats = ref([
  { name: 'QR Code', icon: '📱', description: '二维码' },
  { name: 'Code 128', icon: '📊', description: '一维条形码' },
  { name: 'Code 39', icon: '📋', description: '一维条形码' },
  { name: 'Code 93', icon: '📄', description: '一维条形码' },
  { name: 'EAN-13', icon: '🛒', description: '商品条形码' },
  { name: 'EAN-8', icon: '🏷️', description: '短商品码' },
  { name: 'UPC-A', icon: '🇺🇸', description: '美国商品码' },
  { name: 'UPC-E', icon: '📦', description: '短美国码' },
  { name: 'Data Matrix', icon: '⬜', description: '数据矩阵码' },
  { name: 'PDF417', icon: '📜', description: '二维条形码' },
  { name: 'Aztec', icon: '🔷', description: '阿兹特克码' },
  { name: 'ITF', icon: '📏', description: '交叉25码' }
])

// 初始化
onMounted(() => {
  checkSupport()
})

// 清理资源
onUnmounted(() => {
  stopCamera()
  if (detectionInterval) {
    clearInterval(detectionInterval)
  }
})

// 监听连续检测状态
watch(continuousDetection, (enabled) => {
  if (enabled && isCameraActive.value) {
    startContinuousDetection()
  } else {
    stopContinuousDetection()
  }
})

// 检查浏览器支持
const checkSupport = async () => {
  try {
    isSupported.value = 'BarcodeDetector' in window
    
    if (isSupported.value) {
      barcodeDetector = new (window as any).BarcodeDetector()
      
      // 获取支持的格式
      if ((window as any).BarcodeDetector.getSupportedFormats) {
        const formats = await (window as any).BarcodeDetector.getSupportedFormats()
        console.log('支持的格式:', formats)
      }
    }
  } catch (err) {
    console.error('检查支持失败:', err)
    isSupported.value = false
  }
}

// 启动摄像头检测
const startCameraDetection = async () => {
  try {
    error.value = ''
    
    mediaStream = await navigator.mediaDevices.getUserMedia({ 
      video: { 
        facingMode: 'environment' // 优先使用后置摄像头
      } 
    })
    
    if (videoElement.value) {
      videoElement.value.srcObject = mediaStream
      isCameraActive.value = true
      
      // 等待视频加载
      videoElement.value.onloadedmetadata = () => {
        setupOverlayCanvas()
      }
    }
  } catch (err) {
    console.error('启动摄像头失败:', err)
    error.value = err instanceof Error ? err.message : '启动摄像头失败'
  }
}

// 停止摄像头
const stopCamera = () => {
  if (mediaStream) {
    mediaStream.getTracks().forEach(track => track.stop())
    mediaStream = null
  }
  
  isCameraActive.value = false
  continuousDetection.value = false
  stopContinuousDetection()
}

// 设置覆盖层画布
const setupOverlayCanvas = () => {
  if (overlayCanvas.value && videoElement.value) {
    const canvas = overlayCanvas.value
    const video = videoElement.value
    
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight
  }
}

// 拍照检测
const captureFrame = async () => {
  if (!videoElement.value || !barcodeDetector) return
  
  await detectBarcodes(videoElement.value)
}

// 开始连续检测
const startContinuousDetection = () => {
  if (detectionInterval) return
  
  detectionInterval = setInterval(async () => {
    if (videoElement.value && barcodeDetector && !isDetecting.value) {
      await detectBarcodes(videoElement.value)
    }
  }, 1000) // 每秒检测一次
}

// 停止连续检测
const stopContinuousDetection = () => {
  if (detectionInterval) {
    clearInterval(detectionInterval)
    detectionInterval = null
  }
}

// 处理文件上传
const handleFileUpload = (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  
  if (file) {
    const reader = new FileReader()
    reader.onload = (e) => {
      currentImage.value = e.target?.result as string
    }
    reader.readAsDataURL(file)
  }
}

// 从URL检测
const detectFromUrl = () => {
  if (imageUrl.value.trim()) {
    currentImage.value = imageUrl.value.trim()
    showUrlInput.value = false
  }
}

// 图片加载完成
const onImageLoad = async () => {
  if (imageElement.value && barcodeDetector) {
    await detectBarcodes(imageElement.value)
    setupImageOverlay()
  }
}

// 图片加载错误
const onImageError = () => {
  error.value = '图片加载失败，请检查URL是否正确或图片是否支持跨域访问'
}

// 设置图片覆盖层
const setupImageOverlay = () => {
  if (imageOverlayCanvas.value && imageElement.value) {
    const canvas = imageOverlayCanvas.value
    const img = imageElement.value
    
    canvas.width = img.naturalWidth
    canvas.height = img.naturalHeight
    
    // 绘制检测框
    drawBoundingBoxes(canvas, detectedBarcodes.value)
  }
}

// 检测条形码
const detectBarcodes = async (source: HTMLVideoElement | HTMLImageElement) => {
  try {
    isDetecting.value = true
    error.value = ''
    
    const barcodes = await barcodeDetector.detect(source)
    detectedBarcodes.value = barcodes
    hasDetected.value = true
    
    // 添加到历史记录
    barcodes.forEach((barcode: DetectedBarcode) => {
      addToHistory(barcode.rawValue, barcode.format)
    })
    
    // 绘制检测框
    if (source === videoElement.value && overlayCanvas.value) {
      drawBoundingBoxes(overlayCanvas.value, barcodes)
    }
    
  } catch (err) {
    console.error('检测条形码失败:', err)
    error.value = err instanceof Error ? err.message : '检测条形码失败'
  } finally {
    isDetecting.value = false
  }
}

// 绘制边界框
const drawBoundingBoxes = (canvas: HTMLCanvasElement, barcodes: DetectedBarcode[]) => {
  const ctx = canvas.getContext('2d')
  if (!ctx) return
  
  // 清除之前的绘制
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  
  // 绘制检测框
  barcodes.forEach((barcode, index) => {
    const { x, y, width, height } = barcode.boundingBox
    
    // 绘制边界框
    ctx.strokeStyle = '#00d4ff'
    ctx.lineWidth = 3
    ctx.strokeRect(x, y, width, height)
    
    // 绘制标签
    ctx.fillStyle = '#00d4ff'
    ctx.font = '16px Arial'
    ctx.fillText(`${barcode.format}`, x, y - 5)
    
    // 绘制角点
    ctx.fillStyle = '#ff6b6b'
    barcode.cornerPoints.forEach(point => {
      ctx.beginPath()
      ctx.arc(point.x, point.y, 4, 0, 2 * Math.PI)
      ctx.fill()
    })
  })
}

// 添加到历史记录
const addToHistory = (value: string, format: string) => {
  // 避免重复添加相同的值
  const exists = detectionHistory.value.some(record => 
    record.value === value && record.format === format
  )
  
  if (!exists) {
    detectionHistory.value.push({
      value,
      format,
      timestamp: Date.now()
    })
    
    // 只保留最近50条记录
    if (detectionHistory.value.length > 50) {
      detectionHistory.value.splice(0, detectionHistory.value.length - 50)
    }
  }
}

// 复制到剪贴板
const copyToClipboard = async (text: string) => {
  try {
    await navigator.clipboard.writeText(text)
    // 这里可以添加成功提示
  } catch (err) {
    console.error('复制失败:', err)
  }
}

// 清空历史记录
const clearHistory = () => {
  detectionHistory.value = []
}

// 格式化时间
const formatTime = (timestamp: number): string => {
  return new Date(timestamp).toLocaleTimeString('zh-CN')
}
</script>
